package cz.jm.web.manhunter.client.form;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.core.shared.GWT;
import com.google.gwt.user.client.ui.Widget;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.Img;
import com.smartgwt.client.widgets.form.events.HasSubmitValuesHandlers;
import com.smartgwt.client.widgets.form.fields.FormItem;
import com.smartgwt.client.widgets.layout.VLayout;

import cz.jm.web.manhunter.client.common.FormPanel;
import cz.jm.web.manhunter.client.common.MessagePanel;
import cz.jm.web.manhunter.client.common.MessagePanel.MessageType;
import cz.jm.web.manhunter.client.common.StandardDecoratedPanel;

/**
 * Trieda predstavuje jednoduche formularove view, ktore poskytuje prednastaveny
 * vzhlad formularov aplikacie a naviac doplna moznosti zobrazovania 
 * hlasok a ikon. Formular ma moznosti nastavenia odsadenia od vrchu a spodu
 * vyhradenej oblasti pre zobrazenie. Obsah je horizontalne centrovany na stred.
 * Pre formular je poskytnuta klasicka validacia ako pre SmartGWT, ktora je doplnena 
 * o automaticke zobrazovanie a schovavanie chybovej hlasky validacie. 
 * */
public class BasicFormView implements FormView {

	/** Defaultne odsadenia od vrchnej casti vyhradenej pre vizualizaciu. */
	public static final String DEFAULT_TOP_EMPTY_SPACE_SIZE = "10%";
	/** Defaultne odsadenia od spodnej casti vyhradenej pre vizualizaciu. */
	public static final String DEFAULT_BOTTOM_EMPTY_SPACE_SIZE = "*";
	/** Defaultna velkost vysky a sirky ikony. */
	public static final int DEFAULT_ICON_SIZE = 80;
	/** Defaultny padding pouzity pre ikonu. */
	public static final int DEFAULT_ICON_PADDING = 20;

	private final FormViewBaseConstants constants = GWT.create(FormViewBaseConstants.class);

	/** Hlavny panel view. */
	private final VLayout mainPanel = new VLayout();
	
	/** Zoznam dekoracnych wrapperov pre spravy. */
	private final List<StandardDecoratedPanel> messageWrappers = new ArrayList<StandardDecoratedPanel>();
	
	/** Panel obsahujuci chybovu hlasku validacie. */
	private MessagePanel validationFailMessage = MessagePanel.getMessagePanel(MessageType.ERROR,
	        constants.defaultFailMessage());
	
	/** Samotny formular. */
	private final FormPanel formPanel = new FormPanel();
	/** Odsadenie od vrchnej casti v oblasti vyhradenej pre zobrazenie. */
	private final Canvas topSpacer = new Canvas();
	
	private final VLayout messageHolder = new VLayout();
	/** Odsadenie od spodnej casti v oblasti vyhradenej pre zobrazenie. */
	private final  Canvas bottomSpacer = new Canvas();
	/** Placeholder pre zobrazenie ikony. */
	private final Canvas iconHolder = new Canvas();
	
	public BasicFormView() {
		// Na celu plochu
		mainPanel.setWidth100();
		mainPanel.setHeight100();

		// Odsadenie formularu od vrchu vyhradenej oblasti
		topSpacer.setHeight(DEFAULT_TOP_EMPTY_SPACE_SIZE);
		mainPanel.addMember(topSpacer);

		// Inicializacia formulara.

		StandardDecoratedPanel standardPanel = new StandardDecoratedPanel();
		iconHolder.setAutoHeight();
		iconHolder.setAutoWidth();
		standardPanel.getWorkLayout().addMember(iconHolder);
		standardPanel.getWorkLayout().addMember(formPanel.getForm());

		mainPanel.addMember(standardPanel.asHLayout());

		messageHolder.setHeight100();
		messageHolder.setWidth100();
		mainPanel.addMember(messageHolder);
		// Inicializacia volnej oblasti pod formularom.
		bottomSpacer.setHeight(DEFAULT_BOTTOM_EMPTY_SPACE_SIZE);
		mainPanel.addMember(bottomSpacer);
	}

	
	
	
	/**
	 * Nastavenie zobrazenia ikony. Defaultne sa pouzije odsadenie
	 * {@value #DEFAULT_ICON_PADDING} a rozmer {@link #DEFAULT_ICON_SIZE}.
	 * 
	 * @param path
	 *            cesta k ikone
	 * @see #setIcon(String, int, int)
	 * @see #setIcon(Img)
	 */
	public void setIcon(String path) {
		setIcon(path, DEFAULT_ICON_SIZE, DEFAULT_ICON_SIZE);
	}

	/**
	 * Nastavenie zobrazenia ikony. Defaultne sa pouzije odsadenie
	 * {@value #DEFAULT_ICON_PADDING}.
	 * 
	 * @param path
	 *            cesta k ikone
	 * @param width
	 *            sirka zobrazenia ikony
	 * @param height
	 *            vyska zobrazenia ikony
	 * @see #setIcon(String)
	 * @see #setIcon(Img)
	 */
	public void setIcon(String path, int width, int height) {
		Img img = new Img(path, width, height);
		img.setPadding(DEFAULT_ICON_PADDING);
		setIcon(img);
	}

	/**
	 * Nastavenie zobrazenia ikony. Na obrazok sa neaplikuju ziadne dodatocne
	 * nastavenia je zobrazeny tak ako si to je nastavene zvonku.
	 * 
	 * @param img
	 *            obrazok ktory sa pouzije ako ikona
	 * @see #setIcon(String, int, int)
	 * @see #setIcon(String)
	 */
	public void setIcon(Img img) {
		removeIcon();
		iconHolder.addChild(img);
	}

	/** Odstranenie ikony zo zobrazenia. */
	public void removeIcon() {
		for (Canvas child : iconHolder.getChildren()) {
			iconHolder.removeChild(child);
		}
	}

	/** Nastavenie odsadenia od vrchnej casti oblasti vyhradenej pre vizualizaciu. */
	public void setTopSpacerSize(String size) {
		topSpacer.setHeight(size);
	}

	/** Nastavenie odsadenia od spodnej casti oblasti vyhradenej pre vizualizaciu. */
	public void setBottomSpacerSize(String size) {
		bottomSpacer.setHeight(size);
	}

	/** Nastavenie popisku buttonu pre submit. */
	public void setSubmitButtonTitle(String title) {
		formPanel.getSubmitButton().setTitle(title);
	}

	/**
	 * Vlozenie poloziek do formulara. Vkladane polozky (items) mozu
	 * predpokladat ze formular ma standardne dva stlpce.
	 * 
	 * @param items
	 *            polozky formulara
	 * */
	public void setFields(FormItem... items) {
		formPanel.setFields(items);
	}
	
	/** Zobrazenie chybovej spravy pri nepodarenej validacii formularu. 
	 * Pomocna fcia pre casto opakovanu cinnost validaciu, resp.chybovu hlasku validacie.
	 * @param failedItems zoznam popiskov poloziek formularu pre ktore sa nepodarila validacia. */
	private void showValidationFailedMessage(List<String> failedItems) {
		hideValidationFailedMessage();
		validationFailMessage = MessagePanel.getMessagePanel(MessageType.ERROR, constants.validationFailMessage() + " " + failedItems.toString());
		addMessage(validationFailMessage);
//		// Priznak zobrazenia validacnej chybovej spravy.
//		// Az po showFailMessage ta totiz automaticky ruzi tento priznak.
//		setShownAutoValidationFailMessage(true);
	}

	private void hideValidationFailedMessage() {
		removeMessage(validationFailMessage);
	}
	
//	@Override
//	public Canvas asCanvas() {
//		return mainPanel;
//	}

	@Override
	public HasSubmitValuesHandlers getSubmit() {
		return formPanel.getForm();
	}

	
	@Override 
	public void addMessage(MessagePanel message) {
		StandardDecoratedPanel x = new StandardDecoratedPanel(); 
		x.getWorkLayout().addMember(message.asCanvas());
		x.setHeaderCloseButton(true);
		messageWrappers.add(x);
		messageHolder.addMember(x.asHLayout());
	}
	
	@Override 
	public void removeMessage(MessagePanel message) {
		for (StandardDecoratedPanel p : messageWrappers) {
			if (p.getWorkLayout().contains(message.asCanvas())) {
				messageHolder.removeMember(p.asHLayout());
				p.getWorkLayout().removeMember(message.asCanvas());
				break;
			}
		}
	}
	
//	@Override
//	public void hideFailMessage() {
//		// Skrytie chybovej spravy znamena zrusnie priznaku zobraznia 
//		// validacnej chybovej spravy.
//		setShownAutoValidationFailMessage(false);		
//		closeFailInfoLayout.asHLayout().hide();
//	}

	@Override
    public void setSubmitable(boolean submitable) {
	    formPanel.setSubmitable(submitable);	    
    }

	@Override
	public boolean validate() {
		boolean isValid = formPanel.getForm().validate();
		// Pokial nie je validny -> chybova hlaska.
		if (isValid) {
			hideValidationFailedMessage();
		}
		else {
			// Rucna kontrola skrz vsetky polozky formularu a vyber tych co nie su validne.
			FormItem[] items = formPanel.getForm().getFields();
			List<String> failedItemTitles = new ArrayList<String>();
			for (FormItem item : items) {
				if (!item.validate()) {
					failedItemTitles.add(item.getTitle());
				}
			}
			if (!failedItemTitles.isEmpty()) {
				showValidationFailedMessage(failedItemTitles);				
			}
		}
		
		return isValid;
	}




	@Override
    public Widget asWidget() {
	    // TODO Auto-generated method stub
	    return null;
    }

}
